﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace NakedSanta
{
    class Copter : GameObject
    {
        Vector3 direction = new Vector3(0, 0, -1);

        Color color = Color.Black;
        private float mainRotorPos = 4.2f;
        private Vector3 tailRotorPos = new Vector3(8, 2, 2.5f);
        private float rotateSpeed = 0.8f;
        private float throttleSpeed = 2.5f;
        private float tiltSpeed = 0.005f;
        private float maxTiltAngle = 90; //in degrees
        private float stabilizationSpeed = 0.007f;
        private MouseState originalMouseState;
        private float groundLevel = -3.9f;

        public Copter(GraphicsDevice graphicsDevice)
        {
            Mouse.SetPosition(graphicsDevice.Viewport.Width / 2, graphicsDevice.Viewport.Height / 2);
            originalMouseState = Mouse.GetState();

            this.graphicsDevice = graphicsDevice;

            InitializeVertices();
            InitializeIndices();
            SetNormals();
            vertexBuffer = new VertexBuffer(graphicsDevice, typeof(VertexPositionColorNormal), vertices.Length, BufferUsage.WriteOnly);
            indexBuffer = new IndexBuffer(graphicsDevice, typeof(short), indices.Length, BufferUsage.WriteOnly);

            vertexBuffer.SetData<VertexPositionColorNormal>(vertices);
            indexBuffer.SetData<short>(indices);

            scale = Vector3.One / 35;
            velocity = Vector3.Left;

            //Add main rotor
            Rotor mainRotor = new Rotor(graphicsDevice);
            mainRotor.position.Y = mainRotorPos;
            mainRotor.scale = Vector3.One*1.7f;
            children.Add(mainRotor);
            //Add tail rotor
            Rotor tailRotor = new Rotor(graphicsDevice);
            tailRotor.position = tailRotorPos;
            tailRotor.rotation = Quaternion.CreateFromAxisAngle(Vector3.Left, (float)Math.PI / 2);
            tailRotor.scale = Vector3.One/2;
            children.Add(tailRotor);
        }

        private void InitializeVertices()
        {
            vertices = new VertexPositionColorNormal[82];

            //Left side
            vertices[0] = new VertexPositionColorNormal{ Position = new Vector3(-1, 3, 2), Color = color };
            vertices[1] = new VertexPositionColorNormal{ Position = new Vector3(4, 3, 2), Color = color };
            vertices[2] = new VertexPositionColorNormal{ Position = new Vector3(7, 3, 2), Color = color };
            vertices[3] = new VertexPositionColorNormal{ Position = new Vector3(8, 3, 2), Color = color };
            vertices[4] = new VertexPositionColorNormal{ Position = new Vector3(8, 4, 2), Color = color };
            vertices[5] = new VertexPositionColorNormal{ Position = new Vector3(9, 4, 2), Color = color };
            vertices[6] = new VertexPositionColorNormal{ Position = new Vector3(9, 1, 2), Color = color };
            vertices[7] = new VertexPositionColorNormal{ Position = new Vector3(8, 1, 2), Color = color };
            vertices[8] = new VertexPositionColorNormal{ Position = new Vector3(8, 0, 2), Color = color };
            vertices[9] = new VertexPositionColorNormal{ Position = new Vector3(5, 0, 2), Color = color };
            vertices[10] = new VertexPositionColorNormal{ Position = new Vector3(4, 0, 2), Color = color };
            vertices[11] = new VertexPositionColorNormal{ Position = new Vector3(4, -1, 2), Color = color };
            vertices[12] = new VertexPositionColorNormal{ Position = new Vector3(4, -2, 2), Color = color };
            vertices[13] = new VertexPositionColorNormal{ Position = new Vector3(3, -2, 2), Color = color };
            vertices[14] = new VertexPositionColorNormal{ Position = new Vector3(3, -3, 2), Color = color };
            vertices[15] = new VertexPositionColorNormal{ Position = new Vector3(-1, -2, 2), Color = color };
            vertices[16] = new VertexPositionColorNormal{ Position = new Vector3(-3, -3, 2), Color = color };
            vertices[17] = new VertexPositionColorNormal{ Position = new Vector3(-3, -2, 2), Color = color };
            vertices[18] = new VertexPositionColorNormal{ Position = new Vector3(-4, -2, 2), Color = color };
            vertices[19] = new VertexPositionColorNormal{ Position = new Vector3(-6, -2, 2), Color = color };
            vertices[20] = new VertexPositionColorNormal{ Position = new Vector3(-6, 0, 2), Color = color };
            vertices[21] = new VertexPositionColorNormal{ Position = new Vector3(-4, 0, 2), Color = color };
            vertices[22] = new VertexPositionColorNormal{ Position = new Vector3(-4, 1, 2), Color = color };
            vertices[23] = new VertexPositionColorNormal{ Position = new Vector3(-1, 1, 2), Color = color };
            vertices[24] = new VertexPositionColorNormal{ Position = new Vector3(-1, 3, 2), Color = Color.LightBlue };
            vertices[25] = new VertexPositionColorNormal{ Position = new Vector3(-1, 1, 2), Color = Color.Blue };
            vertices[26] = new VertexPositionColorNormal{ Position = new Vector3(-4, 1, 2), Color = Color.LightBlue };

            //Right side
            vertices[27] = new VertexPositionColorNormal{ Position = new Vector3(-1, 3, -2), Color = color };
            vertices[28] = new VertexPositionColorNormal{ Position = new Vector3(4, 3, -2), Color = color };
            vertices[29] = new VertexPositionColorNormal{ Position = new Vector3(7, 3, -2), Color = color };
            vertices[30] = new VertexPositionColorNormal{ Position = new Vector3(8, 3, -2), Color = color };
            vertices[31] = new VertexPositionColorNormal{ Position = new Vector3(8, 4, -2), Color = color };
            vertices[32] = new VertexPositionColorNormal{ Position = new Vector3(9, 4, -2), Color = color };
            vertices[33] = new VertexPositionColorNormal{ Position = new Vector3(9, 1, -2), Color = color };
            vertices[34] = new VertexPositionColorNormal{ Position = new Vector3(8, 1, -2), Color = color };
            vertices[35] = new VertexPositionColorNormal{ Position = new Vector3(8, 0, -2), Color = color };
            vertices[36] = new VertexPositionColorNormal{ Position = new Vector3(5, 0, -2), Color = color };
            vertices[37] = new VertexPositionColorNormal{ Position = new Vector3(4, 0, -2), Color = color };
            vertices[38] = new VertexPositionColorNormal{ Position = new Vector3(4, -1, -2), Color = color };
            vertices[39] = new VertexPositionColorNormal{ Position = new Vector3(4, -2, -2), Color = color };
            vertices[40] = new VertexPositionColorNormal{ Position = new Vector3(3, -2, -2), Color = color };
            vertices[41] = new VertexPositionColorNormal{ Position = new Vector3(3, -3, -2), Color = color };
            vertices[42] = new VertexPositionColorNormal{ Position = new Vector3(-1, -2, -2), Color = color };
            vertices[43] = new VertexPositionColorNormal{ Position = new Vector3(-3, -3, -2), Color = color };
            vertices[44] = new VertexPositionColorNormal{ Position = new Vector3(-3, -2, -2), Color = color };
            vertices[45] = new VertexPositionColorNormal{ Position = new Vector3(-4, -2, -2), Color = color };
            vertices[46] = new VertexPositionColorNormal{ Position = new Vector3(-6, -2, -2), Color = color };
            vertices[47] = new VertexPositionColorNormal{ Position = new Vector3(-6, 0, -2), Color = color };
            vertices[48] = new VertexPositionColorNormal{ Position = new Vector3(-4, 0, -2), Color = color };
            vertices[49] = new VertexPositionColorNormal{ Position = new Vector3(-4, 1, -2), Color = color };
            vertices[50] = new VertexPositionColorNormal{ Position = new Vector3(-1, 1, -2), Color = color };
            vertices[51] = new VertexPositionColorNormal{ Position = new Vector3(-1, 3, -2), Color = Color.LightBlue };
            vertices[52] = new VertexPositionColorNormal{ Position = new Vector3(-1, 1, -2), Color = Color.Blue };
            vertices[53] = new VertexPositionColorNormal{Position = new Vector3(-4, 1, -2), Color = Color.LightBlue};

            vertices[54] = new VertexPositionColorNormal { Position = new Vector3(-1, 3, 2), Color = color };
            vertices[55] = new VertexPositionColorNormal { Position = new Vector3(7, 3, 2), Color = color };
            vertices[56] = new VertexPositionColorNormal { Position = new Vector3(8, 4, 2), Color = color };
            vertices[57] = new VertexPositionColorNormal { Position = new Vector3(9, 4, 2), Color = color };
            vertices[58] = new VertexPositionColorNormal { Position = new Vector3(9, 1, 2), Color = color };
            vertices[59] = new VertexPositionColorNormal { Position = new Vector3(8, 0, 2), Color = color };
            vertices[60] = new VertexPositionColorNormal { Position = new Vector3(5, 0, 2), Color = color };
            vertices[61] = new VertexPositionColorNormal { Position = new Vector3(4, -1, 2), Color = color };
            vertices[62] = new VertexPositionColorNormal { Position = new Vector3(4, -2, 2), Color = color };
            vertices[63] = new VertexPositionColorNormal { Position = new Vector3(3, -3, 2), Color = color };
            vertices[64] = new VertexPositionColorNormal { Position = new Vector3(-3, -3, 2), Color = color };
            vertices[65] = new VertexPositionColorNormal { Position = new Vector3(-6, -2, 2), Color = color };
            vertices[66] = new VertexPositionColorNormal { Position = new Vector3(-6, 0, 2), Color = color };
            vertices[67] = new VertexPositionColorNormal { Position = new Vector3(-4, 1, 2), Color = color };
            vertices[68] = new VertexPositionColorNormal { Position = new Vector3(-1, 3, -2), Color = color };
            vertices[69] = new VertexPositionColorNormal { Position = new Vector3(7, 3, -2), Color = color };
            vertices[70] = new VertexPositionColorNormal { Position = new Vector3(8, 4, -2), Color = color };
            vertices[71] = new VertexPositionColorNormal { Position = new Vector3(9, 4, -2), Color = color };
            vertices[72] = new VertexPositionColorNormal { Position = new Vector3(9, 1, -2), Color = color };
            vertices[73] = new VertexPositionColorNormal { Position = new Vector3(8, 0, -2), Color = color };
            vertices[74] = new VertexPositionColorNormal { Position = new Vector3(5, 0, -2), Color = color };
            vertices[75] = new VertexPositionColorNormal { Position = new Vector3(4, -1, -2), Color = color };
            vertices[76] = new VertexPositionColorNormal { Position = new Vector3(4, -2, -2), Color = color };
            vertices[77] = new VertexPositionColorNormal { Position = new Vector3(3, -3, -2), Color = color };
            vertices[78] = new VertexPositionColorNormal { Position = new Vector3(-3, -3, -2), Color = color };
            vertices[79] = new VertexPositionColorNormal { Position = new Vector3(-6, -2, -2), Color = color };
            vertices[80] = new VertexPositionColorNormal { Position = new Vector3(-6, 0, -2), Color = color };
            vertices[81] = new VertexPositionColorNormal { Position = new Vector3(-4, 1, -2), Color = color };
        }

        private void InitializeIndices()
        {
            indices = new short[198];

            //Left side
            indices[0] = 0;
            indices[1] = 12;
            indices[2] = 15;

            indices[3] = 0;
            indices[4] = 1;
            indices[5] = 12;

            indices[6] = 1;
            indices[7] = 8;
            indices[8] = 10;

            indices[9] = 1;
            indices[10] = 3;
            indices[11] = 8;

            indices[12] = 3;
            indices[13] = 2;
            indices[14] = 4;

            indices[15] = 4;
            indices[16] = 6;
            indices[17] = 7;

            indices[18] = 4;
            indices[19] = 5;
            indices[20] = 6;

            indices[21] = 7;
            indices[22] = 6;
            indices[23] = 8;

            indices[24] = 10;
            indices[25] = 9;
            indices[26] = 11;

            indices[27] = 13;
            indices[28] = 12;
            indices[29] = 14;

            indices[30] = 17;
            indices[31] = 14;
            indices[32] = 16;

            indices[33] = 17;
            indices[34] = 13;
            indices[35] = 14;

            indices[36] = 19;
            indices[37] = 17;
            indices[38] = 16;

            indices[39] = 20;
            indices[40] = 18;
            indices[41] = 19;

            indices[42] = 20;
            indices[43] = 21;
            indices[44] = 18;

            indices[45] = 20;
            indices[46] = 22;
            indices[47] = 21;

            indices[48] = 22;
            indices[49] = 15;
            indices[50] = 18;

            indices[51] = 22;
            indices[52] = 23;
            indices[53] = 15;

            indices[54] = 24;
            indices[55] = 25;
            indices[56] = 26;

            //Right side
            indices[57] = 27;
            indices[58] = 42;
            indices[59] = 39;

            indices[60] = 27;
            indices[61] = 39;
            indices[62] = 28;

            indices[63] = 28;
            indices[64] = 37;
            indices[65] = 35;

            indices[66] = 28;
            indices[67] = 35;
            indices[68] = 30;

            indices[69] = 30;
            indices[70] = 31;
            indices[71] = 29;

            indices[72] = 31;
            indices[73] = 34;
            indices[74] = 33;

            indices[75] = 31;
            indices[76] = 33;
            indices[77] = 32;

            indices[78] = 34;
            indices[79] = 35;
            indices[80] = 33;

            indices[81] = 37;
            indices[82] = 38;
            indices[83] = 36;

            indices[84] = 40;
            indices[85] = 41;
            indices[86] = 39;

            indices[87] = 44;
            indices[88] = 43;
            indices[89] = 41;

            indices[90] = 44;
            indices[91] = 41;
            indices[92] = 40;

            indices[93] = 46;
            indices[94] = 43;
            indices[95] = 44;

            indices[96] = 47;
            indices[97] = 46;
            indices[98] = 45;

            indices[99] = 47;
            indices[100] = 45;
            indices[101] = 48;

            indices[102] = 47;
            indices[103] = 48;
            indices[104] = 49;

            indices[105] = 49;
            indices[106] = 45;
            indices[107] = 42;

            indices[108] = 49;
            indices[109] = 42;
            indices[110] = 50;

            indices[111] = 51;
            indices[112] = 53;
            indices[113] = 52;

            // windscreen
            indices[114] = 24;
            indices[115] = 26;
            indices[116] = 53;

            indices[117] = 24;
            indices[118] = 53;
            indices[119] = 51;

            //roof
            indices[120] = 54;
            indices[121] = 68;
            indices[122] = 69;

            indices[123] = 54;
            indices[124] = 69;
            indices[125] = 55;

            // roof - back wing
            indices[126] = 55;
            indices[127] = 69;
            indices[128] = 56;

            indices[129] = 70;
            indices[130] = 56;
            indices[131] = 69;

            indices[132] = 70;
            indices[133] = 57;
            indices[134] = 56;

            indices[135] = 70;
            indices[136] = 71;
            indices[137] = 57;

            //back
            indices[138] = 57;
            indices[139] = 72;
            indices[140] = 58;

            indices[141] = 57;
            indices[142] = 71;
            indices[143] = 72;

            indices[144] = 58;
            indices[145] = 73;
            indices[146] = 59;

            indices[147] = 58;
            indices[148] = 72;
            indices[149] = 73;

            indices[150] = 59;
            indices[151] = 74;
            indices[152] = 60;

            indices[153] = 59;
            indices[154] = 73;
            indices[155] = 74;

            indices[156] = 60;
            indices[157] = 75;
            indices[158] = 61;

            indices[159] = 60;
            indices[160] = 74;
            indices[161] = 75;

            indices[162] = 61;
            indices[163] = 76;
            indices[164] = 62;

            indices[165] = 61;
            indices[166] = 75;
            indices[167] = 76;

            indices[168] = 62;
            indices[169] = 77;
            indices[170] = 63;

            indices[171] = 62;
            indices[172] = 76;
            indices[173] = 77;

            indices[174] = 63;
            indices[175] = 78;
            indices[176] = 64;

            indices[177] = 63;
            indices[178] = 77;
            indices[179] = 78;

            indices[180] = 64;
            indices[181] = 79;
            indices[182] = 65;

            indices[183] = 64;
            indices[184] = 78;
            indices[185] = 79;

            indices[186] = 65;
            indices[187] = 80;
            indices[188] = 66;

            indices[189] = 65;
            indices[190] = 79;
            indices[191] = 80;

            indices[192] = 66;
            indices[193] = 81;
            indices[194] = 67;

            indices[195] = 66;
            indices[196] = 80;
            indices[197] = 81;
        }

        private void SetNormals()
        {
            int verticesInLeftSide = 27;
            for (int i = 0; i < verticesInLeftSide; i++)
            {
                vertices[i].Normal = Vector3.Right;
            }

            int verticesInRightSide = verticesInLeftSide*2;
            for (int i = verticesInLeftSide; i < verticesInRightSide; i++)
            {
                vertices[i].Normal = Vector3.Left;
            }

            vertices[54].Normal = Vector3.Up;
            vertices[55].Normal = Vector3.Up;
            vertices[56].Normal = Vector3.Up;
            vertices[57].Normal = Vector3.Up;
            vertices[58].Normal = Vector3.Backward;
            vertices[59].Normal = Vector3.Backward;
            vertices[60].Normal = Vector3.Backward;
            vertices[61].Normal = Vector3.Up;
            vertices[62].Normal = Vector3.Up;
        }

        internal void ProcessInput(float amount)
        {
            //Mouse controls
            Matrix rot = Matrix.CreateFromQuaternion(rotation);
            MouseState currentMouseState = Mouse.GetState();
            if (currentMouseState != originalMouseState && position.Y > groundLevel)
            {
                float xDifference = currentMouseState.X - originalMouseState.X;
                float yDifference = currentMouseState.Y - originalMouseState.Y;
                double forwardRotationAngle = Math.Atan2(rot.Up.Y, rot.Up.Z) * (180.0 / Math.PI);
                double leftRotationAngle = Math.Atan2(rot.Up.Y, rot.Up.X) * (180.0 / Math.PI);

                if (forwardRotationAngle > 90 - maxTiltAngle && yDifference > 0 || forwardRotationAngle < 90 + maxTiltAngle && yDifference < 0)
                    rotation *= Quaternion.CreateFromAxisAngle(Vector3.Forward, (tiltSpeed * yDifference * amount));

                if (leftRotationAngle > 90 - maxTiltAngle && xDifference > 0 || leftRotationAngle < 90 + maxTiltAngle && xDifference < 0)
                    rotation *= Quaternion.CreateFromAxisAngle(Vector3.Left, (tiltSpeed * xDifference * amount));

                Mouse.SetPosition(graphicsDevice.Viewport.Width / 2, graphicsDevice.Viewport.Height / 2);
            }

            KeyboardState keyState = Keyboard.GetState();

            if (keyState.IsKeyDown(Keys.W))
                position.Y += throttleSpeed * amount;
            if (keyState.IsKeyDown(Keys.S))
                if (position.Y > groundLevel)
                    position.Y -= throttleSpeed * amount;
            if (keyState.IsKeyDown(Keys.A))
                rotation *= Quaternion.CreateFromAxisAngle(Vector3.Up, rotateSpeed * amount);
            if (keyState.IsKeyDown(Keys.D))
                rotation *= Quaternion.CreateFromAxisAngle(Vector3.Up, -rotateSpeed * amount);

            if (position.Y > groundLevel)
            {
                position += rot.Up * 0.5f;
                position.Y -= 0.5f;
            }
            //stabilize copter
            rot.Up = Vector3.Up;
            rotation = Quaternion.Lerp(rotation, Quaternion.CreateFromRotationMatrix(rot), stabilizationSpeed);
        }
    }
}
